package cn.skyquant.quant4j.task.boot.task;

import cn.skyquant.quant4j.api.dto.ResultDTO;
import cn.skyquant.quant4j.api.http.HttpService;
import cn.skyquant.quant4j.sdk.enums.CompareType;
import cn.skyquant.quant4j.sdk.enums.TradeDirection;
import cn.skyquant.quant4j.sdk.util.log.LogUtil;
import cn.skyquant.quant4j.sdk.util.time.CalendarUtils;
import cn.skyquant.quant4j.sdk.util.time.Period;
import cn.skyquant.quant4j.task.boot.entity.Economics;
import cn.skyquant.quant4j.task.boot.entity.EconomicsCategory;
import cn.skyquant.quant4j.task.boot.entity.EconomicsCategoryImpact;
import cn.skyquant.quant4j.task.boot.repository.EconomicsCategoryImpactRepository;
import cn.skyquant.quant4j.task.boot.repository.EconomicsCategoryRepository;
import cn.skyquant.quant4j.task.boot.repository.EconomicsRepository;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.locks.ReentrantLock;

@RestController
@RequestMapping("/economics")
public class EconomicsTask {

    @Autowired
    EconomicsRepository economicsRepository;

    @Autowired
    EconomicsCategoryRepository economicsCategoryRepository;

    @Autowired
    EconomicsCategoryImpactRepository economicsCategoryImpactRepository;

    @Autowired
    HttpService httpService;

    @Value("${economics.fetchMaxDay}")
    int fetchMaxDay;

    @Value("${task.run}")
    boolean taskrun;

    public static int _max_date = 7;//抓取最大日期后7天的数据

    private static final SimpleDateFormat _yyyy = new SimpleDateFormat("yyyy");
    private static final SimpleDateFormat _mmdd = new SimpleDateFormat("MMdd");
    private static TimeZone GMT = TimeZone.getTimeZone("GMT");

    @Scheduled(cron = "0 0 0 ? * *")
    @RequestMapping(value = "/daily", method = RequestMethod.GET)
    public void dailyEconomics() {
        SimpleDateFormat format_gmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        format_gmt.setTimeZone(GMT);

        SimpleDateFormat format_cst = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        Date today = CalendarUtils.getFirstTime(new Date(), Period.daily);
        Date lastDate = economicsRepository.getMaxRecordDate();
        Date endDate = CalendarUtils.addDate(today, _max_date);//抓取的结束日期永远是今天之后的7天
        Date beginDate;
        if (lastDate == null) {
            beginDate = CalendarUtils.addDate(today, -fetchMaxDay);
        } else {
            beginDate = CalendarUtils.addDate(lastDate, 1);
        }
        Date indexDate = beginDate;
        while (indexDate.getTime() <= endDate.getTime()) {
            String yyyy = _yyyy.format(indexDate);
            String mmdd = _mmdd.format(indexDate);
            String url = "https://rili.jin10.com/datas/" + yyyy + "/" + mmdd + "/economics.json";

            JSONArray jsonArray = httpService.getArray(url, null, null, null);
            List<Economics> economicsList = Lists.newArrayList();
            Set<Integer> ids = new HashSet<>();
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject jsonObject = jsonArray.getJSONObject(i);
                if (jsonObject.getInteger("id") == null || jsonObject.getInteger("datanameId") == null) {
                    continue;
                }
                int datanameId = jsonObject.getInteger("datanameId");
                int id = jsonObject.getInteger("id");
                String country = jsonObject.getString("country");
                int star = jsonObject.getInteger("star");
                String dataname = jsonObject.getString("dataname");

                try {
                    EconomicsCategory economicsCategory = economicsCategoryRepository.get(datanameId);
                    if (economicsCategory == null) {
                        String jie_url = "https://rili.jin10.com/datas/jiedu/" + id + ".json";
                        JSONObject jieObject = httpService.get(jie_url, null, null, null);
                        if (jieObject == null) {
                            continue;
                        }
                        EconomicsCategory category = new EconomicsCategory();
                        category.institutions = jieObject.getString("institutions");
                        category.frequency = jieObject.getString("frequency");
                        category.method = jieObject.getString("method");
                        category.impact = jieObject.getString("impact");
                        category.paraphrase = jieObject.getString("paraphrase");
                        category.focus = jieObject.getString("focus");
                        category.country = country;
                        category.star = star;
                        category.dataname = dataname;
                        category.id = datanameId;
                        economicsCategoryRepository.insert(category);
                    }
                    Economics economics = new Economics();
                    economics.id = id;
                    economics.yingxiang = jsonObject.getInteger("yingxiang");
                    economics.country = country;
                    economics.actual = jsonObject.getDouble("actual");
                    economics.consensus = jsonObject.getDouble("consensus");
                    economics.unit = jsonObject.getString("unit");
                    economics.revised = jsonObject.getString("revised");
                    economics.star = star;
                    economics.previous = jsonObject.getDouble("previous");
                    economics.dataname = jsonObject.getString("dataname");
                    economics.publicTime = CalendarUtils.parseStandard(jsonObject.getString("publictime"));
                    economics.publicTimeGmt = format_gmt.format(economics.publicTime);
                    economics.publicTimeCst = format_cst.format(economics.publicTime);
                    economics.publicTimestamp = economics.publicTime.getTime();
                    economics.timeshow = jsonObject.getString("time_show");
                    economics.timestr = jsonObject.getString("timestr");
                    economics.datanameId = jsonObject.getInteger("datanameId");
                    economics.datename = jsonObject.getString("datename");
                    economics.title = jsonObject.getString("title");
                    economics.statusName = jsonObject.getString("status_name");
                    economics.statusClass = jsonObject.getString("status_class");
                    economics.recordTime = CalendarUtils.getFirstTime(indexDate, Period.daily);
                    Date date = new Date();
                    economics.updatedTimeGmt = format_gmt.format(date);
                    economics.updatedTimeCst = format_cst.format(date);
                    economics.updatedTimestamp = date.getTime();
                    economics.updatedNum = 1;
                    ids.add(economics.id);
                    economicsList.add(economics);
                } catch (Exception e) {
                    LogUtil.error("parse date error[" + id + "]:" + jsonObject.toJSONString(), e);
                    continue;
                }
            }
            if (!ids.isEmpty()) {
                Set<Integer> dbIds = economicsRepository.findByIds(ids);
                //先删除后增加
                if (!dbIds.isEmpty()) {
                    economicsRepository.deleteByIds(dbIds);
                }
            }

            if (!economicsList.isEmpty()) {
                economicsRepository.batchInsert(economicsList);
            }
            indexDate = CalendarUtils.addDate(indexDate, 1);
        }
    }

    private static Object lock_Economics = new ReentrantLock();

    @Scheduled(cron = "*/5 * * * * *")
    public void updateEconomicsTask30() {
        if (taskrun) {
            updateEconomicsTask(30);
        }
    }

    @Scheduled(cron = "*/13 * * * * *")
    public void updateEconomicsTask100() {
        if (taskrun) {
            updateEconomicsTask(100);
        }
    }

    @Scheduled(cron = "0 * * * * *")
    public void updateEconomicsTask200() {
        if (taskrun) {
            updateEconomicsTask(300);
        }
    }

    @RequestMapping(value = "/update/{num}", method = RequestMethod.GET)
    private void updateEconomicsTask(@PathVariable int num) {
        SimpleDateFormat format_gmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        format_gmt.setTimeZone(GMT);

        SimpleDateFormat format_cst = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        synchronized (lock_Economics) {
            Date thedate = new Date();
            List<Economics> economicsList = economicsRepository.getPublicTime(thedate, num);
            //现在比较麻烦的就是，根据这批economicsList找到对应的date日期
            Set<String> stringSet = new HashSet<>();
            Set<Integer> idSet = new HashSet<>();
            economicsList.forEach(x -> {
                Date publicTime = x.publicTime;
                String format = CalendarUtils.formatOption(publicTime);
                stringSet.add(format);
                idSet.add(x.id);
            });
            stringSet.forEach(x -> {
                String yyyy = x.substring(0, 4);
                String mmdd = x.substring(4, 8);
                String url = "https://rili.jin10.com/datas/" + yyyy + "/" + mmdd + "/economics.json";
                JSONArray jsonArray = httpService.getArray(url, null, null, null);
                for (int i = 0; i < jsonArray.size(); i++) {
                    JSONObject jsonObject = jsonArray.getJSONObject(i);
                    if (jsonObject.getInteger("id") == null) {
                        continue;
                    }
                    Integer id = jsonObject.getInteger("id");
                    if (!idSet.contains(id)) {
                        continue;
                    }
                    String statusName = jsonObject.getString("status_name");
                    if ("未公布".equals(statusName)) {
                        continue;
                    }
                    Economics economics = new Economics();
                    economics.id = id;
                    economics.actual = jsonObject.getDouble("actual");
                    economics.statusName = statusName;
                    economics.statusClass = jsonObject.getString("status_class");
                    economics.consensus = jsonObject.getDouble("consensus");
                    Date date = new Date();
                    economics.updatedTimeGmt = format_gmt.format(date);
                    economics.updatedTimeCst = format_cst.format(date);
                    economics.updatedTimestamp = date.getTime();
                    economicsRepository.update(economics);
                    idSet.remove(economics.id);
                }
            });
            //剩下的idSet就是仍然未公布的,只更新一次updateNum
            idSet.forEach(x -> economicsRepository.updateNum(x));
        }
    }

    static Map<String, String> map = new HashMap<>();

    static {
        map.put("美元", "USD");
        map.put("欧元", "EUR");
        map.put("日元", "JPY");
        map.put("英镑", "GBP");
        map.put("瑞郎", "CHF");
        map.put("加元", "CAD");
        map.put("澳元", "AUD");
        map.put("纽元", "NZD");
        map.put("黄金", "XAU");
        map.put("港元", "HKD");
        map.put("原油价格", "WTI");
        map.put("原油", "WTI");
        map.put("新加坡元", "SGD");
        map.put("坡元", "SGD");
        map.put("韩元", "KRW");
        map.put("新台币", "TWD");
        map.put("台币", "TWD");
        map.put("天然气", "CFD");
        map.put("卢比", "INR");
    }

    @RequestMapping(value = "/impact/2", method = RequestMethod.GET)
    public ResultDTO<Integer> impack2() {
        List<EconomicsCategory> nullList = economicsCategoryRepository.findNullImpact();
        int num = 0;
        for (EconomicsCategory ec : nullList) {
            Integer id = economicsRepository.getByDatanameId(ec.id);
            if (id == null) {
                continue;
            }
            String jie_url = "https://rili.jin10.com/datas/jiedu/" + id + ".json";
            JSONObject jieObject = httpService.get(jie_url, null, null, null);
            if (jieObject == null) {
                continue;
            }
            EconomicsCategory category = new EconomicsCategory();
            category.institutions = jieObject.getString("institutions");
            category.frequency = jieObject.getString("frequency");
            category.method = jieObject.getString("method");
            category.impact = jieObject.getString("impact");
            category.paraphrase = jieObject.getString("paraphrase");
            category.focus = jieObject.getString("focus");
            category.country = jieObject.getString("country");
            category.star = jieObject.getInteger("star");
            category.dataname = jieObject.getString("dataname");
            category.id = ec.id;
            if (category.impact != null) {
                num += economicsCategoryRepository.update(category);
            }
        }
        return ResultDTO.success(num);
    }


    //分析类目
    @RequestMapping(value = "/impact/1", method = RequestMethod.GET)
    public ResultDTO<Long> impact1() {
        long begin = System.currentTimeMillis();
        List<EconomicsCategory> all = economicsCategoryRepository.findAll();
        for (int i = 0; i < all.size(); i++) {
            EconomicsCategory category = all.get(i);
            String impact = category.impact;
            if (impact == null) {
                continue;
            }
            String[] str = impact.split("[,;，；]");
            if (str == null || str.length == 0) {
                continue;
            }
            for (String s : str) {
                if (
                        s.contains("公布值>预期值=")
                                || s.contains("公布值<预期值=")
                                || s.contains("公布值>预测值=")
                                || s.contains("公布值<预测值=")
                                || s.contains("实际值>预期值=")
                                || s.contains("实际值<预期值=")
                                || s.contains("实际值>预测值=")
                                || s.contains("实际值<预测值=")
                                || s.contains("数据>预期=")
                                || s.contains("数据<预期=")
                                || s.contains("数据>前值=")
                                || s.contains("数据<前值=")) {
                    String[] s1 = s.split("=");
                    if (s1.length == 2) {
                        EconomicsCategoryImpact entity = new EconomicsCategoryImpact();
                        if ("公布值>预期值".equals(s1[0]) || "公布值>预测值".equals(s1[0]) || "实际值>预测值".equals(s1[0]) || "实际值>预期值".equals(s1[0]) || "数据>预期".equals(s1[0])) {
                            entity.type = CompareType.DGE;
                        } else if ("公布值<预期值".equals(s1[0]) || "公布值<预测值".equals(s1[0]) || "实际值<预测值".equals(s1[0]) || "实际值<预期值".equals(s1[0]) || "数据<预期".equals(s1[0])) {
                            entity.type = CompareType.DLE;
                        } else if ("数据>前值".equals(s1[0])) {
                            entity.type = CompareType.DGP;
                        } else if ("数据<前值".equals(s1[0])) {
                            entity.type = CompareType.DLP;
                        } else {
                            continue;
                        }
                        if ("利多".equals(s1[1].substring(0, 2)) || "利好".equals(s1[1].substring(0, 2))) {
                            entity.td = TradeDirection.LONG;
                        } else if ("利空".equals(s1[1].substring(0, 2))) {
                            entity.td = TradeDirection.SHORT;
                        } else {
                            continue;
                        }

                        String symbol_char = s1[1].substring(2, s1[1].length());
                        if (!map.containsKey(symbol_char)) {
                            continue;
                        }
                        entity.symbol = map.get(symbol_char);
                        entity.category = category;
                        Set<EconomicsCategoryImpact> set = economicsCategoryImpactRepository.findByCategory(category.id);
                        if (!set.contains(entity)) {
                            try {
                                economicsCategoryImpactRepository.insert(entity);
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }
        }
        return ResultDTO.success(System.currentTimeMillis() - begin);
    }
}
